﻿//----------------------------------------------------------------
// <copyright file="MptInitializerTest.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//----------------------------------------------------------------

using System.Collections.Generic;
using System.Globalization;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MptCodeLibrary;
using MptCodeLibrary.Configuration;
using MptCodeLibrary.Exceptions;
using MptCodeLibrary.TeamFoundation;
using NMock2;

namespace Test.UnitTest
{
    /// <summary>
    /// Summary description for MptInitializerTest
    /// </summary>
    [TestClass]
    public class MptInitializerTest : UnitTestBase
    {
        private ITeamFoundationFacade teamFoundationFacadeMock;
        private IMptConfiguration mptConfigurationMock;

        private MptInitializer mptInitializer;

        private const string path = "somepath";
        private const string tfsServerName = "tfsServerName";
        private string emptyFilter;

        private List<string> workItemTypes;

        private List<TeamServerConfiguration> tfsServers;

        // Use TestInitialize to run code before running each test 
         [TestInitialize]
         public void TestInitialize()
         {
             teamFoundationFacadeMock = Mocks.NewMock<ITeamFoundationFacade>();
             mptConfigurationMock = Mocks.NewMock<IMptConfiguration>();

             tfsServers = new List<TeamServerConfiguration> {new TeamServerConfiguration {ServerName = tfsServerName}};
             workItemTypes = new List<string> {"Value Proposition", "Feature Group", "Feature", "Deliverable" };

             mptInitializer = new MptInitializer(mptConfigurationMock, teamFoundationFacadeMock);

             StringBuilder sb = new StringBuilder();
             sb.Append(@"""CoreFields/StringFields/Field[ReferenceName='System.WorkItemType']/NewValue"" = 'Value Proposition'");
             sb.Append(@" OR ""CoreFields/StringFields/Field[ReferenceName='System.WorkItemType']/NewValue"" = 'Feature Group'");
             sb.Append(@" OR ""CoreFields/StringFields/Field[ReferenceName='System.WorkItemType']/NewValue"" = 'Feature'");
             sb.Append(@" OR ""CoreFields/StringFields/Field[ReferenceName='System.WorkItemType']/NewValue"" = 'Deliverable'");

             emptyFilter = string.Format(CultureInfo.InvariantCulture, MptInitializer.ExpressionForWitTypeFilter,
                                         sb);

         }

        // Use TestCleanup to run code after each test has run
         [TestCleanup]
         public void TestCleanup()
         {
             
         }
        
        [TestMethod, ExpectedException(typeof(MptException))]
        public void SubscribeToEventsThrowsExceptionIfNoTeamServersDefined()
        {
            Expect.Once.On(mptConfigurationMock).GetProperty("TeamServers").Will(Return.Value(new List<TeamServerConfiguration>()));
            
            mptInitializer.SubscribeToEvents(path);
            Mocks.VerifyAllExpectationsHaveBeenMet();
        }

        [TestMethod]
        public void VerifySubscribeToEventForSingleTeamServer()
        {
            Expect.Once.On(mptConfigurationMock).GetProperty("TeamServers").Will(Return.Value(tfsServers));
            Expect.Once.On(mptConfigurationMock).GetProperty("TeamProjects").Will(Return.Value(new List<string>()));

            Expect.Once.On(teamFoundationFacadeMock).Method("GetEventWorkItemTypesForProjects")
                .Will(Return.Value(workItemTypes));

            Expect.Once.On(teamFoundationFacadeMock).Method("SignupForReceivingEvent").With(tfsServerName, path, emptyFilter);

            mptInitializer.SubscribeToEvents(path);

            Mocks.VerifyAllExpectationsHaveBeenMet();
        }

        [TestMethod]
        public void VerifySubscribeToEventForMultipleTeamServers()
        {
            const string tfsServerName2 = "tfsServerName2";

            tfsServers.Add(new TeamServerConfiguration{ServerName = tfsServerName2});

            Expect.Once.On(mptConfigurationMock).GetProperty("TeamServers").Will(Return.Value(tfsServers));
            Expect.Once.On(mptConfigurationMock).GetProperty("TeamProjects").Will(Return.Value(new List<string>()));
            Expect.Once.On(teamFoundationFacadeMock).Method("GetEventWorkItemTypesForProjects")
                .Will(Return.Value(workItemTypes));

            Expect.Once.On(teamFoundationFacadeMock).Method("SignupForReceivingEvent").With(tfsServerName, path, emptyFilter);
            Expect.Once.On(teamFoundationFacadeMock).Method("SignupForReceivingEvent").With(tfsServerName2, path, emptyFilter);

            mptInitializer.SubscribeToEvents(path);

            Mocks.VerifyAllExpectationsHaveBeenMet();
        }

        [TestMethod]
        public void VerifySubscribeToEventForSpecificProject()
        {
            List<string> projectNames = new List<string> {"Project1"};
            string filterExpression = "(\"PortfolioProject\" = 'Project1') AND " + emptyFilter;

            Expect.Once.On(mptConfigurationMock).GetProperty("TeamServers").Will(Return.Value(tfsServers));
            Expect.Once.On(mptConfigurationMock).GetProperty("TeamProjects").Will(Return.Value(projectNames));
            Expect.Once.On(teamFoundationFacadeMock).Method("GetEventWorkItemTypesForProjects")
                .Will(Return.Value(workItemTypes));

            Expect.Once.On(teamFoundationFacadeMock).Method("SignupForReceivingEvent").With(tfsServerName, path, filterExpression);

            mptInitializer.SubscribeToEvents(path);

            Mocks.VerifyAllExpectationsHaveBeenMet();
        }
        
        [TestMethod]
        public void VerifySubscribeToEventForThreeProjects()
        {
            List<string> projectNames = new List<string> { "Project1", "Project2", "Project3" };
            string filterExpression = "(\"PortfolioProject\" = 'Project1' OR \"PortfolioProject\" = 'Project2' OR \"PortfolioProject\" = 'Project3') AND " + emptyFilter;

            Expect.Once.On(mptConfigurationMock).GetProperty("TeamServers").Will(Return.Value(tfsServers));
            Expect.Once.On(mptConfigurationMock).GetProperty("TeamProjects").Will(Return.Value(projectNames));

            Expect.Once.On(teamFoundationFacadeMock).Method("GetEventWorkItemTypesForProjects")
                .Will(Return.Value(workItemTypes));

            Expect.Once.On(teamFoundationFacadeMock).Method("SignupForReceivingEvent").With(tfsServerName, path, filterExpression);

            mptInitializer.SubscribeToEvents(path);

            Mocks.VerifyAllExpectationsHaveBeenMet();
        }

        [TestMethod]
        public void VerifySubscribeToEventForOneWorkItemType()
        {
            string filterExpression = string.Format(CultureInfo.InvariantCulture, MptInitializer.ExpressionForWitTypeFilter,
                            @"""CoreFields/StringFields/Field[ReferenceName='System.WorkItemType']/NewValue"" = 'Value Proposition'");
            
            Expect.Once.On(mptConfigurationMock).GetProperty("TeamServers").Will(Return.Value(tfsServers));
            Expect.Once.On(mptConfigurationMock).GetProperty("TeamProjects").Will(Return.Value(new List<string>()));
            
            Expect.Once.On(teamFoundationFacadeMock).Method("GetEventWorkItemTypesForProjects")
                .Will(Return.Value(new List<string> { "Value Proposition" }));

            Expect.Once.On(teamFoundationFacadeMock).Method("SignupForReceivingEvent").With(tfsServerName, path, filterExpression);

            mptInitializer.SubscribeToEvents(path);

            Mocks.VerifyAllExpectationsHaveBeenMet();
            
        }
    }
}
